import tkinter as tk
from tkinter import ttk


class AutocompleteCombobox(ttk.Combobox):
    def __init__(self, parent, values, **kwargs):
        ttk.Combobox.__init__(self, parent, values=values, **kwargs)
        self.set_var()
        self.bind("<KeyRelease>", self.on_key_release)
        self.bind("<FocusIn>", self.on_focus_in)

    def set_var(self):
        self.var = tk.StringVar()
        self.var.trace("w", self.on_var_change)
        self["textvariable"] = self.var

    def on_key_release(self, event):
        if event.keysym == "BackSpace":
            self.completion_list = []
        else:
            self.autocomplete()

    def on_focus_in(self, event):
        self.autocomplete()

    def on_var_change(self, *args):
        self.autocomplete()

    def autocomplete(self):
        if self.var.get() == "":
            self.completion_list = []
            return

        value = self.var.get()
        matches = [s for s in self['values'] if s.startswith(value)]
        if matches:
            self.completion_list = matches
            if len(matches) == 1:
                self.event_generate("<<ComboboxSelected>>")
            else:
                self.set(self.completion_list[0])
                self.dropdown_show()
        else:
            self.dropdown_hide()

    def dropdown_show(self):
        self.tk.call("tk::ComboboxPopup", self._w, "%d,%d,%d,%d" % (
            self.winfo_rootx(),
            self.winfo_rooty() + self.winfo_height(),
            self.winfo_width(),
            200))

    def dropdown_hide(self):
        self.tk.call("tk::ComboboxPopup", self._w, "")

# class AutocompleteCombobox(ttk.Combobox):
#     def __init__(self, parent, values, **kwargs):
#         self.values_ = values
#         # if 'command' in kwargs:
#         #     self.command = kwargs['command']
#         #     del kwargs['command']
#         # else:
#         #     self.command = None
#         ttk.Combobox.__init__(self, parent, values=values, **kwargs)
#         self.bind("<KeyRelease>", self.on_key_release)
#         # if self.command is not None:
#         #     self.bind("<<ComboboxSelected>>", lambda e: self.command())
# 
#     def on_key_release(self, event):
#         if event.keysym in ('BackSpace', 'Escape', 'space'):
#             # 如果按下的是空格、退格、回车或Esc键，不处理
#             return
#         else:
#             # 获取用户输入的文本
#             user_input = self.get()
#             # 过滤出以用户输入开头的选项
#             matches = [s for s in self.values_ if s.lower().startswith(user_input.lower())]
#             # 如果没有匹配项，则清空下拉列表
#             if not matches:
#                 self['values'] = ()
#             else:
#                 # 设置下拉列表的值为匹配项，并自动选择第一个匹配项
#                 self['values'] = matches
#                 # self.current(0)  # 选择第一个值，但不下拉列表

